//SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package board_member_api_serv

import (
	"context"
	"time"

	"gitcode.com/eteam/api-server/api_common"
	"gitcode.com/eteam/api-server/dao"
	"gitcode.com/eteam/api-server/dao/board_dao"
	"gitcode.com/eteam/api-server/dao/user_dao"
	"gitcode.com/eteam/api-server/notice_serv"
	"gitcode.com/eteam/proto-gen-go.git/board_member_api"
	"gitcode.com/eteam/proto-gen-go.git/notices/notices_board"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *BoardMemberApiImpl) SetAdmin(ctx context.Context, req *board_member_api.SetAdminRequest) (*board_member_api.SetAdminResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_member_api.SetAdminResponse{
			Code:   board_member_api.SetAdminResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//不能更新自己的权限
	if sessItem.UserId == req.MemberUserId {
		return &board_member_api.SetAdminResponse{
			Code:   board_member_api.SetAdminResponse_CODE_NOT_ALLOW,
			ErrMsg: "不能更新自己的权限",
		}, nil
	}
	//检查权限
	memberItem, err := board_dao.MemberInfoDao.Get(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return &board_member_api.SetAdminResponse{
			Code:   board_member_api.SetAdminResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !memberItem.Admin {
		return &board_member_api.SetAdminResponse{
			Code:   board_member_api.SetAdminResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	//检查目标成员是否存在
	exist, err := board_dao.MemberInfoDao.Exist(ctx, req.BoardId, req.MemberUserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &board_member_api.SetAdminResponse{
			Code:   board_member_api.SetAdminResponse_CODE_NO_MEMBER,
			ErrMsg: "画板成员不存在",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = board_dao.MemberInfoDao.UpdateAdmin(sessCtx, req.BoardId, req.MemberUserId, req.Admin)
		if err != nil {
			return nil, err
		}
		return &board_member_api.SetAdminResponse{
			Code: board_member_api.SetAdminResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go notice_serv.PublishToUser(req.MemberUserId, &notices_board.UpdateBoardMemberPermNotice{
		BoardId:      req.BoardId,
		MemberUserId: req.MemberUserId,
	})
	return ret.(*board_member_api.SetAdminResponse), nil
}

func (apiImpl *BoardMemberApiImpl) UpdateViewTime(ctx context.Context, req *board_member_api.UpdateViewTimeRequest) (*board_member_api.UpdateViewTimeResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_member_api.UpdateViewTimeResponse{
			Code:   board_member_api.UpdateViewTimeResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查成员信息是否存在
	exist, err := board_dao.MemberInfoDao.Exist(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &board_member_api.UpdateViewTimeResponse{
			Code:   board_member_api.UpdateViewTimeResponse_CODE_NO_BROAD,
			ErrMsg: "没有权限",
		}, nil
	}

	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = board_dao.MemberInfoDao.UpdateLastViewTime(sessCtx, req.BoardId, sessItem.UserId, nowTime)
		if err != nil {
			return nil, err
		}
		return &board_member_api.UpdateViewTimeResponse{
			Code: board_member_api.UpdateViewTimeResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*board_member_api.UpdateViewTimeResponse), nil
}

func (apiImpl *BoardMemberApiImpl) Remove(ctx context.Context, req *board_member_api.RemoveRequest) (*board_member_api.RemoveResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_member_api.RemoveResponse{
			Code:   board_member_api.RemoveResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//不能删除自己
	if sessItem.UserId == req.MemberUserId {
		return &board_member_api.RemoveResponse{
			Code:   board_member_api.RemoveResponse_CODE_NOT_ALLOW,
			ErrMsg: "不能删除自己",
		}, nil
	}
	//检查权限
	memberItem, err := board_dao.MemberInfoDao.Get(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return &board_member_api.RemoveResponse{
			Code:   board_member_api.RemoveResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !memberItem.Admin {
		return &board_member_api.RemoveResponse{
			Code:   board_member_api.RemoveResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	//检查目标成员是否存在
	exist, err := board_dao.MemberInfoDao.Exist(ctx, req.BoardId, req.MemberUserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &board_member_api.RemoveResponse{
			Code: board_member_api.RemoveResponse_CODE_OK,
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = api_common.LeaveBoard(sessCtx, req.BoardId, req.MemberUserId)
		if err != nil {
			return nil, err
		}
		return &board_member_api.RemoveResponse{
			Code: board_member_api.RemoveResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go notice_serv.PublishToBoard(req.BoardId, &notices_board.LeaveBoardNotice{
		BoardId:      req.BoardId,
		MemberUserId: req.MemberUserId,
	})
	go notice_serv.PublishToUser(req.MemberUserId, &notices_board.LeaveBoardNotice{
		BoardId:      req.BoardId,
		MemberUserId: req.MemberUserId,
	})
	return ret.(*board_member_api.RemoveResponse), nil
}

func (apiImpl *BoardMemberApiImpl) Leave(ctx context.Context, req *board_member_api.LeaveRequest) (*board_member_api.LeaveResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_member_api.LeaveResponse{
			Code:   board_member_api.LeaveResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查是否存在
	exist, err := board_dao.MemberInfoDao.Exist(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &board_member_api.LeaveResponse{
			Code: board_member_api.LeaveResponse_CODE_OK,
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = api_common.LeaveBoard(sessCtx, req.BoardId, sessItem.UserId)
		if err != nil {
			return nil, err
		}
		return &board_member_api.LeaveResponse{
			Code: board_member_api.LeaveResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go notice_serv.PublishToBoard(req.BoardId, &notices_board.LeaveBoardNotice{
		BoardId:      req.BoardId,
		MemberUserId: sessItem.UserId,
	})
	go notice_serv.PublishToUser(sessItem.UserId, &notices_board.LeaveBoardNotice{
		BoardId:      req.BoardId,
		MemberUserId: sessItem.UserId,
	})
	return ret.(*board_member_api.LeaveResponse), nil

}

func (apiImpl *BoardMemberApiImpl) ListMy(ctx context.Context, req *board_member_api.ListMyRequest) (*board_member_api.ListMyResponse, error) {
	emptyList := []*board_member_api.MemberInfo{}

	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_member_api.ListMyResponse{
			Code:       board_member_api.ListMyResponse_CODE_WRONG_SESSION,
			ErrMsg:     "会话不存在",
			MemberList: emptyList,
		}, nil
	}
	memberItemList, err := board_dao.MemberInfoDao.ListByMember(ctx, sessItem.UserId, false, []string{})
	if err != nil {
		return nil, err
	}

	//生成结果
	memberList, err := apiImpl.convertToMemberList(ctx, memberItemList, false, sessItem.UserId)
	if err != nil {
		return nil, err
	}

	return &board_member_api.ListMyResponse{
		Code:       board_member_api.ListMyResponse_CODE_OK,
		MemberList: memberList,
	}, nil
}

func (apiImpl *BoardMemberApiImpl) List(ctx context.Context, req *board_member_api.ListRequest) (*board_member_api.ListResponse, error) {
	emptyList := []*board_member_api.MemberInfo{}

	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_member_api.ListResponse{
			Code:       board_member_api.ListResponse_CODE_WRONG_SESSION,
			ErrMsg:     "会话不存在",
			MemberList: emptyList,
		}, nil
	}
	//检查是否在画板成员中
	myMemberItem, err := board_dao.MemberInfoDao.Get(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return &board_member_api.ListResponse{
			Code:       board_member_api.ListResponse_CODE_NO_PERMISSION,
			ErrMsg:     "没有权限",
			MemberList: emptyList,
		}, nil
	}

	memberItemList, err := board_dao.MemberInfoDao.ListByBoard(ctx, req.BoardId)
	if err != nil {
		return nil, err
	}

	//生成结果
	memberList, err := apiImpl.convertToMemberList(ctx, memberItemList, myMemberItem.Admin, sessItem.UserId)
	if err != nil {
		return nil, err
	}

	return &board_member_api.ListResponse{
		Code:       board_member_api.ListResponse_CODE_OK,
		MemberList: memberList,
	}, nil
}

func (apiImpl *BoardMemberApiImpl) Get(ctx context.Context, req *board_member_api.GetRequest) (*board_member_api.GetResponse, error) {
	emptyInfo := &board_member_api.MemberInfo{}

	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_member_api.GetResponse{
			Code:   board_member_api.GetResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
			Member: emptyInfo,
		}, nil
	}
	//检查是否在画板成员中
	myMemberItem, err := board_dao.MemberInfoDao.Get(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return &board_member_api.GetResponse{
			Code:   board_member_api.GetResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
			Member: emptyInfo,
		}, nil
	}
	memberItem, err := board_dao.MemberInfoDao.Get(ctx, req.BoardId, req.MemberUserId)
	if err != nil {
		return &board_member_api.GetResponse{
			Code:   board_member_api.GetResponse_CODE_NO_MEMBER,
			ErrMsg: "画板成员不存在",
			Member: emptyInfo,
		}, nil
	}

	//生成结果
	memberList, err := apiImpl.convertToMemberList(ctx, []*board_dao.MemberInfoDbItem{memberItem}, myMemberItem.Admin, sessItem.UserId)
	if err != nil {
		return nil, err
	}

	if len(memberList) == 0 {
		return &board_member_api.GetResponse{
			Code:   board_member_api.GetResponse_CODE_NO_MEMBER,
			ErrMsg: "画板成员不存在",
			Member: emptyInfo,
		}, nil
	}

	return &board_member_api.GetResponse{
		Code:   board_member_api.GetResponse_CODE_OK,
		Member: memberList[0],
	}, nil
}

func (apiImpl *BoardMemberApiImpl) convertToMemberList(ctx context.Context, memberItemList []*board_dao.MemberInfoDbItem, myAdmin bool, myUserId string) ([]*board_member_api.MemberInfo, error) {
	userIdList := []string{}
	for _, memberItem := range memberItemList {
		userIdList = append(userIdList, memberItem.MemberUserId)
	}
	userItemList, err := user_dao.UserInfoDao.ListById(ctx, userIdList)
	if err != nil {
		return nil, err
	}
	userItemMap := map[string]*user_dao.UserInfoDbItem{}
	for _, userItem := range userItemList {
		userItemMap[userItem.UserId] = userItem
	}

	memberList := []*board_member_api.MemberInfo{}
	for _, memberItem := range memberItemList {
		member := memberItem.ToMemberInfo()
		userItem, ok := userItemMap[member.MemberUserId]
		if ok {
			member.MemberDisplayName = userItem.BasicInfo.DisplayName
			member.MemberLogoUri = userItem.BasicInfo.LogoUri
		}
		member.UserPerm = &board_member_api.UserPerm{
			CanUpdatePerm: myAdmin && member.MemberUserId != myUserId,
			CanRemove:     myAdmin && member.MemberUserId != myUserId,
		}
		memberList = append(memberList, member)
	}
	return memberList, nil
}
